home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / 3dkit1.zip / 3DVTO2D.C < prev    next >
Text File  |  1992-05-25  |  5KB  |  177 lines

  1. /* 3DVto2D.c  -  convert 3DV data to 2-D list format */
  2.  
  3. /* Oscar Garcia <garciao@mof.govt.nz>, May 1992 */
  4.  
  5. /* uses getopt */
  6. int getopt(int argc, char *argv[], char *options);
  7. extern  int optind;
  8. extern char *optarg;
  9.  
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <math.h>
  13.  
  14. #define USAGE "usage: 3DVto2D [/tx] [/nx] [/dx] [input_file [output_file]]\n\
  15. \tIf file names are omitted, the standard i/o streams are used.\n\
  16. \tOptions (with defaults):\n\
  17. \t\t/t0   -  Latitude, degrees\n\
  18. \t\t/n0   -  Longitude, degrees\n\
  19. \t\t/d-3  -  Viewing distance.  Zero gives orthogonal projection.\n\
  20. \t\t             Positive is in user units to object center.\n\
  21. \t\t             Negative is relative to object size.\n\
  22. \t\t             Default -3 is as in 3dv."
  23.  
  24. #define ERROR(msg) {fputs(msg,stderr),exit(1);}
  25. #define PERROR(msg) {perror(msg),exit(1);}
  26.  
  27. #define BIG 3e33
  28. #define EPS 1e-9
  29. #define RADIANS 3.141592/180
  30. #define DDEFAULT -3
  31.  
  32. void main(int argc, char* argv[])
  33. {
  34.     int i, j, n;
  35.     double scale, slon, clon, slat, clat, t[3][3],
  36.         lat = 0, lon = 0, dist = DDEFAULT;
  37.     char options[] = "t:n:d:";
  38.     FILE *infile = stdin, *outfile = stdout;
  39.     typedef double POINT[3];
  40.     POINT min, max, centre, xx, *x;
  41.  
  42.  
  43.     /* get options */
  44.     while ((n = getopt(argc, argv, options)) != EOF)
  45.         if (n == '?')
  46.             ERROR(USAGE)
  47.         else
  48.             switch (n)
  49.             {    case 't':    lat = atof(optarg); break;
  50.                 case 'n':    lon = atof(optarg); break;
  51.                 case 'd':    dist = atof(optarg); break;
  52.             }
  53.  
  54.     /* open files */
  55.     if (optind < argc - 2)
  56.         ERROR(USAGE);    /* too many */
  57.     if (optind < argc)
  58.     {    infile = fopen(argv[optind], "rt");
  59.         if (infile == NULL)
  60.             ERROR("Can't open input file");
  61.         if (++optind < argc)
  62.         {    outfile = fopen(argv[optind], "wt");
  63.             if (outfile == NULL)
  64.                 ERROR("Can't open output file");
  65.         }
  66.     }
  67.  
  68.     /* read points */
  69.     i = fscanf(infile, "%d", &n);
  70.     if (i != 1 || ferror(infile))
  71.         PERROR("Bad input file");
  72. #ifdef __MSDOS__
  73.     if ((unsigned)n * sizeof(POINT) > 0xfff0U)
  74.         ERROR("64k memory block limit exceeded");
  75. #endif
  76.     x = malloc((unsigned)n * sizeof(POINT));
  77.     if (x == NULL)
  78.         ERROR("Out of memory");
  79.     for (j = 0; j < 3; j++)
  80.     {    min[j] = BIG;
  81.         max[j] = -BIG;
  82.     }
  83.     for (i = 0; i < n; i++)
  84.     {    fscanf(infile, "%lf %lf %lf", &x[i][0], &x[i][1], &x[i][2]);
  85.         for (j = 0; j < 3; j++)
  86.         {    if (x[i][j] < min[j])
  87.                 min[j] = x[i][j];
  88.             else if (x[i][j] > max[j])
  89.                 max[j] = x[i][j];
  90.         }
  91.     }
  92.     if (ferror(infile))
  93.         PERROR("Error reading input");
  94.  
  95.     /* get centre and distance */
  96.     for (j = 0, scale = 0.0; j < 3; j++)
  97.     {    centre[j] = (min[j] + max[j]) / 2;
  98.         scale = scale + (max[j] - min[j]) * (max[j] - min[j]);
  99.     }
  100.     if (dist < -EPS)    /* perspective, relative dist; convert to absolute */
  101.         dist *= sqrt(scale * (1 + 0.25 / (dist * dist))) / -0.99;
  102.  
  103.     /* transformation matrix */
  104.     slon = sin(lon * RADIANS);
  105.     clon = cos(lon * RADIANS);
  106.     slat = sin(lat * RADIANS);
  107.     clat = cos(lat * RADIANS);
  108.     t[0][0] = clon;
  109.     t[0][1] = - slon;
  110.     t[1][0] = clat * slon;
  111.     t[1][1] = clat * clon;
  112.     t[1][2] = slat;
  113.     t[2][0] = - slat * slon;
  114.     t[2][1] = - slat * clon;
  115.     t[2][2] = clat;
  116.  
  117.     /* rotate and project along y */
  118.     min[0] = min[2] = BIG;    /* 2-d coords will be saved in 0 and 2 */
  119.     max[0] = max[2] = -BIG;
  120.     for (i = 0; i < n; i++)
  121.     {    for (j = 0; j < 3; j++)
  122.             xx[j] = x[i][j] - centre[j];
  123.         x[i][0] = t[0][0] * xx[0] + t[0][1] * xx[1];
  124.         x[i][1] = t[1][0] * xx[0] + t[1][1] * xx[1] + t[1][2] * xx[2];
  125.         x[i][2] = t[2][0] * xx[0] + t[2][1] * xx[1] + t[2][2] * xx[2];
  126.         if (dist > EPS)        /* perspective */
  127.         {    x[i][0] /= 1 - x[i][1] / dist;
  128.             x[i][2] /= 1 - x[i][1] / dist;
  129.         }    /* x[i][1] not used again here, but might need it some day */
  130.         if (x[i][0] < min[0])
  131.             min[0] = x[i][0];
  132.         else if (x[i][0] > max[0])
  133.             max[0] = x[i][0];
  134.         if (x[i][2] < min[2])
  135.             min[2] = x[i][2];
  136.         else if (x[i][2] > max[2])
  137.             max[2] = x[i][2];
  138.     }
  139.  
  140.     /* factor for scaling to [-1, 1] */
  141.     scale = max[0];
  142.     if (-min[0] > scale)
  143.         scale = -min[0];
  144.     if (max[2] > scale)
  145.         scale = max[2];
  146.     if (-min[2] > scale)
  147.         scale = -min[2];
  148.     scale = 1 / scale;
  149.  
  150.     /* output info */
  151.     fscanf(infile, "%d", &n);
  152.     fprintf(outfile, "# n=%d scale=%g x_range=[%g:%g] y_range=[%g:%g]\n",
  153.         n, 1/scale, scale*min[0], scale*max[0], scale*min[2], scale*max[2]);
  154.     fprintf(outfile, "# latitude=%g longitude=%g distance=%g\n",
  155.         lat, lon, dist);
  156.  
  157.     /* output data */
  158.     while (n-- > 0)
  159.     {    fscanf(infile, "%d %d", &i, &j);
  160.         if (j == 0)
  161.             putc('\n', outfile);        /* blank line (move) */
  162.         fprintf(outfile, "%g %g %d\n",
  163.             scale * x[i-1][0], scale * x[i-1][2], j);
  164.     }
  165.     if (ferror(infile))
  166.         PERROR("Error reading input");
  167.     if (feof(infile))
  168.         ERROR("Unexpected end of file on input");
  169.     fclose(infile);
  170.     if (ferror(outfile))
  171.         PERROR("Error during output");
  172.     fclose(outfile);
  173.  
  174. }
  175.  
  176.  
  177.